package jinyilw.common.file;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.Inflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

public class FileZip
{
	public static byte[] compress(byte[] input)
	{
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		Deflater compressor = new Deflater(1);
		try
		{
			compressor.setInput(input);
			compressor.finish();
			final byte[] buf = new byte[2048];
			while (!compressor.finished())
			{
				int count = compressor.deflate(buf);
				bos.write(buf, 0, count);
			}
		} finally
		{
			compressor.end();
		}
		return bos.toByteArray();
	}

	public static byte[] uncompress(byte[] input) throws DataFormatException
	{
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		Inflater decompressor = new Inflater();
		try
		{
			decompressor.setInput(input);
			final byte[] buf = new byte[2048];
			while (!decompressor.finished())
			{
				int count = decompressor.inflate(buf);
				bos.write(buf, 0, count);
			}
		} finally
		{
			decompressor.end();
		}
		return bos.toByteArray();
	}

	/**
	 * zip文件压缩
	 *
	 * @param inputFile  待压缩文件夹/文件名
	 * @param outputFile 生成的压缩包名字
	 */

	public static void zipCompress(String inputFile, String outputFile)
			throws Exception
	{
		// 创建zip输出流
		ZipOutputStream out = new ZipOutputStream(
				new FileOutputStream(outputFile));
		// 创建缓冲输出流
		BufferedOutputStream bos = new BufferedOutputStream(out);
		File input = new File(inputFile);
		compress(out, bos, input, null);
		bos.close();
		out.close();
	}
	/**
	 * @param name 压缩文件名，可以写为null保持默认
	 */
	public static void compress(ZipOutputStream out, BufferedOutputStream bos,
			File input, String name) throws IOException
	{
		if (name == null)
			name = input.getName();
		// 如果路径为目录（文件夹）
		if (input.isDirectory())
		{
			// 取出文件夹中的文件（或子文件夹）
			File[] list = input.listFiles();
			if (list != null)
				if (list.length == 0)// 如果文件夹为空，则只需在目的地zip文件中写入一个目录进入
				{
					out.putNextEntry(new ZipEntry(name + "/"));
				} else// 如果文件夹不为空，则递归调用compress，文件夹中的每一个文件（或文件夹）进行压缩
				{
					for (File file : list)
						compress(out, bos, file,
								name + "/" + file.getName());
				}
		} else// 如果不是目录（文件夹），即为文件，则先写入目录进入点，之后将文件写入zip文件中
		{
			out.putNextEntry(new ZipEntry(name));
			FileInputStream fos = new FileInputStream(input);
			BufferedInputStream bis = new BufferedInputStream(fos);
			int len = -1;
			// 将源文件写入到zip文件中
			byte[] buf = new byte[1024];
			while ((len = bis.read(buf)) != -1)
				bos.write(buf, 0, len);
			bis.close();
			fos.close();
		}
	}

	/**
	 * 多文件压缩为zip
	 */
	public static void multipleFiles2Zip(List<File> fileList, String zipName)
	{
		FileInputStream nFileInputStream = null;
		ZipOutputStream nZipOutputStream;
		try
		{
			nZipOutputStream = new ZipOutputStream(
					new FileOutputStream(zipName));
			for (File file : fileList)
			{
				nFileInputStream = new FileInputStream(file);
				nZipOutputStream.putNextEntry(new ZipEntry(file.getName()));
				byte[] buf = new byte[2048];
				int len;
				while ((len = nFileInputStream.read(buf)) != -1)
				{
					nZipOutputStream.write(len);
					nZipOutputStream.flush();
				}
			}
			nZipOutputStream.close();
			if (nFileInputStream != null)
			{
				nFileInputStream.close();
			}
		} catch (IOException e)
		{
			e.printStackTrace();
		}
	}

	/**
	 * zip解压
	 *
	 * @param inputFile   待解压文件名
	 * @param destDirPath 解压路径
	 */

	public static void zipUncompress(String inputFile, String destDirPath)
			throws Exception
	{
		File srcFile = new File(inputFile);// 获取当前压缩文件
		// 判断源文件是否存在
		if (!srcFile.exists())
		{
			throw new Exception(srcFile.getPath() + "所指文件不存在");
		}
		// 开始解压
		// 构建解压输入流
		ZipInputStream zIn = new ZipInputStream(new FileInputStream(srcFile));
		ZipEntry entry;
		File file;
		while ((entry = zIn.getNextEntry()) != null)
		{
			if (!entry.isDirectory())
			{
				file = new File(destDirPath, entry.getName());
				if (!file.exists())
					new File(file.getParent()).mkdirs();// 创建此文件的上级目录
				OutputStream out = new FileOutputStream(file);
				BufferedOutputStream bos = new BufferedOutputStream(out);
				int len = -1;
				byte[] buf = new byte[1024];
				while ((len = zIn.read(buf)) != -1)
					bos.write(buf, 0, len);
				// 关流顺序，先打开的后关闭
				bos.close();
				out.close();
			}
		}
		zIn.close();
	}
}
